home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / snd_linux.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  6KB  |  270 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <stdlib.h>
  23. #include <sys/types.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/mman.h>
  26. #include <sys/shm.h>
  27. #include <sys/wait.h>
  28. #include <linux/soundcard.h>
  29. #include <stdio.h>
  30. #include "quakedef.h"
  31.  
  32. int audio_fd;
  33. int snd_inited;
  34.  
  35. static int tryrates[] = { 11025, 22051, 44100, 8000 };
  36.  
  37. qboolean SNDDMA_Init(void)
  38. {
  39.  
  40.     int rc;
  41.     int fmt;
  42.     int tmp;
  43.     int i;
  44.     char *s;
  45.     struct audio_buf_info info;
  46.     int caps;
  47.  
  48.     snd_inited = 0;
  49.  
  50. // open /dev/dsp, confirm capability to mmap, and get size of dma buffer
  51.  
  52.     audio_fd = open("/dev/dsp", O_RDWR);
  53.     if (audio_fd < 0)
  54.     {
  55.         perror("/dev/dsp");
  56.         Con_Printf("Could not open /dev/dsp\n");
  57.         return 0;
  58.     }
  59.  
  60.     rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
  61.     if (rc < 0)
  62.     {
  63.         perror("/dev/dsp");
  64.         Con_Printf("Could not reset /dev/dsp\n");
  65.         close(audio_fd);
  66.         return 0;
  67.     }
  68.  
  69.     if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
  70.     {
  71.         perror("/dev/dsp");
  72.         Con_Printf("Sound driver too old\n");
  73.         close(audio_fd);
  74.         return 0;
  75.     }
  76.  
  77.     if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
  78.     {
  79.         Con_Printf("Sorry but your soundcard can't do this\n");
  80.         close(audio_fd);
  81.         return 0;
  82.     }
  83.  
  84.     if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
  85.     {   
  86.         perror("GETOSPACE");
  87.         Con_Printf("Um, can't do GETOSPACE?\n");
  88.         close(audio_fd);
  89.         return 0;
  90.     }
  91.     
  92.     shm = &sn;
  93.     shm->splitbuffer = 0;
  94.  
  95. // set sample bits & speed
  96.  
  97.     s = getenv("QUAKE_SOUND_SAMPLEBITS");
  98.     if (s) shm->samplebits = atoi(s);
  99.     else if ((i = COM_CheckParm("-sndbits")) != 0)
  100.         shm->samplebits = atoi(com_argv[i+1]);
  101.     if (shm->samplebits != 16 && shm->samplebits != 8)
  102.     {
  103.         ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
  104.         if (fmt & AFMT_S16_LE) shm->samplebits = 16;
  105.         else if (fmt & AFMT_U8) shm->samplebits = 8;
  106.     }
  107.  
  108.     s = getenv("QUAKE_SOUND_SPEED");
  109.     if (s) shm->speed = atoi(s);
  110.     else if ((i = COM_CheckParm("-sndspeed")) != 0)
  111.         shm->speed = atoi(com_argv[i+1]);
  112.     else
  113.     {
  114.         for (i=0 ; i<sizeof(tryrates)/4 ; i++)
  115.             if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
  116.         shm->speed = tryrates[i];
  117.     }
  118.  
  119.     s = getenv("QUAKE_SOUND_CHANNELS");
  120.     if (s) shm->channels = atoi(s);
  121.     else if ((i = COM_CheckParm("-sndmono")) != 0)
  122.         shm->channels = 1;
  123.     else if ((i = COM_CheckParm("-sndstereo")) != 0)
  124.         shm->channels = 2;
  125.     else shm->channels = 2;
  126.  
  127.     shm->samples = info.fragstotal * info.fragsize / (shm->samplebits/8);
  128.     shm->submission_chunk = 1;
  129.  
  130. // memory map the dma buffer
  131.  
  132.     shm->buffer = (unsigned char *) mmap(NULL, info.fragstotal
  133.         * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
  134.     if (!shm->buffer || shm->buffer == (unsigned char *)-1)
  135.     {
  136.         perror("/dev/dsp");
  137.         Con_Printf("Could not mmap /dev/dsp\n");
  138.         close(audio_fd);
  139.         return 0;
  140.     }
  141.  
  142.     tmp = 0;
  143.     if (shm->channels == 2)
  144.         tmp = 1;
  145.     rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
  146.     if (rc < 0)
  147.     {
  148.         perror("/dev/dsp");
  149.         Con_Printf("Could not set /dev/dsp to stereo=%d", shm->channels);
  150.         close(audio_fd);
  151.         return 0;
  152.     }
  153.     if (tmp)
  154.         shm->channels = 2;
  155.     else
  156.         shm->channels = 1;
  157.  
  158.     rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed);
  159.     if (rc < 0)
  160.     {
  161.         perror("/dev/dsp");
  162.         Con_Printf("Could not set /dev/dsp speed to %d", shm->speed);
  163.         close(audio_fd);
  164.         return 0;
  165.     }
  166.  
  167.     if (shm->samplebits == 16)
  168.     {
  169.         rc = AFMT_S16_LE;
  170.         rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
  171.         if (rc < 0)
  172.         {
  173.             perror("/dev/dsp");
  174.             Con_Printf("Could not support 16-bit data.  Try 8-bit.\n");
  175.             close(audio_fd);
  176.             return 0;
  177.         }
  178.     }
  179.     else if (shm->samplebits == 8)
  180.     {
  181.         rc = AFMT_U8;
  182.         rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
  183.         if (rc < 0)
  184.         {
  185.             perror("/dev/dsp");
  186.             Con_Printf("Could not support 8-bit data.\n");
  187.             close(audio_fd);
  188.             return 0;
  189.         }
  190.     }
  191.     else
  192.     {
  193.         perror("/dev/dsp");
  194.         Con_Printf("%d-bit sound not supported.", shm->samplebits);
  195.         close(audio_fd);
  196.         return 0;
  197.     }
  198.  
  199. // toggle the trigger & start her up
  200.  
  201.     tmp = 0;
  202.     rc  = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
  203.     if (rc < 0)
  204.     {
  205.         perror("/dev/dsp");
  206.         Con_Printf("Could not toggle.\n");
  207.         close(audio_fd);
  208.         return 0;
  209.     }
  210.     tmp = PCM_ENABLE_OUTPUT;
  211.     rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
  212.     if (rc < 0)
  213.     {
  214.         perror("/dev/dsp");
  215.         Con_Printf("Could not toggle.\n");
  216.         close(audio_fd);
  217.         return 0;
  218.     }
  219.  
  220.     shm->samplepos = 0;
  221.  
  222.     snd_inited = 1;
  223.     return 1;
  224.  
  225. }
  226.  
  227. int SNDDMA_GetDMAPos(void)
  228. {
  229.  
  230.     struct count_info count;
  231.  
  232.     if (!snd_inited) return 0;
  233.  
  234.     if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
  235.     {
  236.         perror("/dev/dsp");
  237.         Con_Printf("Uh, sound dead.\n");
  238.         close(audio_fd);
  239.         snd_inited = 0;
  240.         return 0;
  241.     }
  242. //    shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
  243. //    fprintf(stderr, "%d    \r", count.ptr);
  244.     shm->samplepos = count.ptr / (shm->samplebits / 8);
  245.  
  246.     return shm->samplepos;
  247.  
  248. }
  249.  
  250. void SNDDMA_Shutdown(void)
  251. {
  252.     if (snd_inited)
  253.     {
  254.         close(audio_fd);
  255.         snd_inited = 0;
  256.     }
  257. }
  258.  
  259. /*
  260. ==============
  261. SNDDMA_Submit
  262.  
  263. Send sound to device if buffer isn't really the dma buffer
  264. ===============
  265. */
  266. void SNDDMA_Submit(void)
  267. {
  268. }
  269.  
  270.